package com.wuliu.system.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wuliu.common.constant.OrderConstants;
import com.wuliu.common.core.domain.entity.SysUser;
import com.wuliu.common.exception.ServiceException;
import com.wuliu.common.utils.*;

import javax.annotation.Resource;

import com.wuliu.system.domain.TspTrack;
import com.wuliu.system.domain.dto.CreateOrderDto;
import com.wuliu.system.service.ITspOrderDetailService;
import com.wuliu.system.service.ITspTrackService;
import com.wuliu.system.service.CommonService;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import com.wuliu.system.mapper.TspOrderMapper;
import com.wuliu.system.domain.TspOrder;
import com.wuliu.system.service.ITspOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 运单Service业务层处理
 *
 * @author realue
 * @date 2023-10-24
 */
@Service
public class TspOrderServiceImpl extends ServiceImpl<TspOrderMapper, TspOrder> implements ITspOrderService {
    @Resource
    private TspOrderMapper tspOrderMapper;
    @Resource
    private CommonService commonService;
    @Resource
    private ITspTrackService tspTrackService;

    /**
     * 查询运单
     *
     * @param id 运单主键
     * @return 运单
     */
    @Override
    public TspOrder selectTspOrderById(String id) {
        return tspOrderMapper.selectTspOrderById(id);
    }

    /**
     * 查询运单列表
     *
     * @param tspOrder 运单
     * @return 运单
     */
    @Override
    public List<TspOrder> selectTspOrderList(TspOrder tspOrder) {
        return tspOrderMapper.selectTspOrderList(tspOrder);
    }

    /**
     * 新增运单
     *
     * @param tspOrder 运单
     * @return 结果
     */
    @Override
    public int insertTspOrder(TspOrder tspOrder) {
        tspOrder.setCreateTime(DateUtils.getNowDate());
        return tspOrderMapper.insertTspOrder(tspOrder);
    }

    /**
     * 修改运单
     *
     * @param tspOrder 运单
     * @return 结果
     */
    @Override
    public int updateTspOrder(TspOrder tspOrder) {
        tspOrder.setUpdateTime(DateUtils.getNowDate());
        return tspOrderMapper.updateTspOrder(tspOrder);
    }

    /**
     * 批量删除运单
     *
     * @param ids 需要删除的运单主键
     * @return 结果
     */
    @Override
    public int deleteTspOrderByIds(String[] ids) {
        return tspOrderMapper.deleteTspOrderByIds(ids);
    }

    /**
     * 删除运单信息
     *
     * @param id 运单主键
     * @return 结果
     */
    @Override
    public int deleteTspOrderById(String id) {
        return tspOrderMapper.deleteTspOrderById(id);
    }

    /**
     * 创建运单
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer createOrder(CreateOrderDto dto) {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        List<TspOrder> tspOrders = new ArrayList<>();
        TspOrder tspOrder = new TspOrder();
        BeanUtil.copyProperties(dto, tspOrder);
        if (StringUtils.isNotEmpty(dto.getOrderNo())) {
            long count = tspOrderMapper.selectCount(new LambdaQueryWrapper<TspOrder>()
                    .eq(TspOrder::getSysAccount, sysUser.getSysAccount())
                    .eq(TspOrder::getOrderNo, dto.getOrderNo()));
            if (count > 0) {
                throw new ServiceException("运单号已存在");
            }
        } else {
            tspOrder.setOrderNo(commonService.createOrderNo(sysUser.getSysAccount(), 1, 1).get(0));
        }
        tspOrder.setId(IdUtil.randomUUID());
        tspOrder.setSysAccount(sysUser.getSysAccount());
        tspOrder.setCreateBy(sysUser.getUserName());
        tspOrder.setCreateTime(DateUtils.getNowDate());
        tspOrder.setStatus(OrderConstants.ORDER_STATUS_2);
        tspOrder.setSourceType(3);
        String address = dto.getSrcProvince() + dto.getSrcCity() + dto.getSrcDistrict() + dto.getSrcAddr();
        Map<String, String> map = TencentLocationUtil.geoCoderRev(address);
        if (null != map) {
            tspOrder.setSrcLng(MapUtils.getString(map, "lng"));
            tspOrder.setSrcLat(MapUtils.getString(map, "lat"));
        }
        address = dto.getDstProvince() + dto.getDstCity() + dto.getDstDistrict() + dto.getDstAddr();
        map = TencentLocationUtil.geoCoderRev(address);
        if (null != map) {
            tspOrder.setDstLng(MapUtils.getString(map, "lng"));
            tspOrder.setDstLat(MapUtils.getString(map, "lat"));
        }
        tspOrders.add(tspOrder);
        //生成子单
        if (tspOrder.getCargoCnt() > 1) {
            tspOrders.addAll(commonService.createSubOrder(tspOrder));
        }
        List<TspTrack> tracks = tspOrders.stream().map(t -> {
            TspTrack tspTrack = new TspTrack();
            tspTrack.setId(IdUtil.randomUUID());
            tspTrack.setOrderId(t.getId());
            tspTrack.setOrderNo(t.getOrderNo());
            tspTrack.setOpTime(DateUtils.getTime());
            tspTrack.setOpCode(OrderConstants.ORDER_STATUS_2);
            tspTrack.setOpUserId(sysUser.getUserId());
            tspTrack.setOpUserName(sysUser.getUserName());
            tspTrack.setDeptId(sysUser.getDeptId());
            tspTrack.setOperation("");
            return tspTrack;
        }).collect(Collectors.toList());
        tspTrackService.saveBatch(tracks);
        this.saveBatch(tspOrders);
        return 1;
    }

    /**
     * 后台导入运单
     *
     * @param orders
     * @return
     */
    @Override
    public String importOrder(List<TspOrder> orders) {
        if (StringUtils.isEmpty(orders)) {
            throw new ServiceException("导入的运单数据不能为空");
        }
        SysUser user = SecurityUtils.getLoginUser().getUser();
        int i = 1;
        int successNum = 0;
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();
        List<TspOrder> tspOrders = new ArrayList<>();
        for (TspOrder order : orders) {
            try {
                String result = checkOrder(order, user.getSysAccount());
                if (StringUtils.isNotEmpty(result)) {
                    failureNum++;
                    failureMsg.append("<br/>第[").append(i).append("]行错误：").append(result);
                } else {
                    order.setId(IdUtil.randomUUID());
                    order.setSysAccount(user.getSysAccount());
                    order.setCreateTime(DateUtils.getNowDate());
                    order.setCreateBy(user.getUserName());
                    order.setSourceType(3);
                    order.setStatus(OrderConstants.ORDER_STATUS_2);
                    String address = order.getSrcProvince() + order.getSrcCity() + order.getSrcDistrict() + order.getSrcAddr();
                    Map<String, String> map = TencentLocationUtil.geoCoderRev(address);
                    if (null != map) {
                        order.setSrcLng(MapUtils.getString(map, "lng"));
                        order.setSrcLat(MapUtils.getString(map, "lat"));
                    }
                    address = order.getDstProvince() + order.getDstCity() + order.getDstDistrict() + order.getDstAddr();
                    map = TencentLocationUtil.geoCoderRev(address);
                    if (null != map) {
                        order.setDstLng(MapUtils.getString(map, "lng"));
                        order.setDstLat(MapUtils.getString(map, "lat"));
                    }
                    tspOrders.add(order);
                    successNum++;
                }
                i++;
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/> 第[" + i + "]导入失败：";
                failureMsg.append(msg).append(e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！共 " + failureNum + " 条数据不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            int j = 0;
            List<TspOrder> noOrderNos = tspOrders.stream().filter(t -> StringUtils.isBlank(t.getOrderNo())).collect(Collectors.toList());
            if (StringUtils.isNotEmpty(noOrderNos)) {
                List<String> orderNos = commonService.createOrderNo(user.getSysAccount(), 1, noOrderNos.size());
                for (TspOrder order : noOrderNos) {
                    order.setOrderNo(orderNos.get(j));
                    j++;
                }
            }
            //生成子单
            List<TspOrder> rtOrders = tspOrders.stream().filter(t -> t.getCargoCnt() > 1).collect(Collectors.toList());
            rtOrders.forEach(t -> tspOrders.addAll(commonService.createSubOrder(t)));
            try {
                this.saveBatch(tspOrders, 100);
                //successMsg.insert(0, "数据导入成功！共 " + successNum + " 条，数据如下：");
                return "数据导入成功！共[" + successNum + "]条";
            } catch (Exception e) {
                return "运单导入失败：" + e.getMessage();
            }
        }
    }

    /**
     * 校验导入数据
     *
     * @param order
     * @param sysAccount
     * @return
     */
    private String checkOrder(TspOrder order, String sysAccount) {
        if (StringUtils.isAnyBlank(order.getSrcName(), order.getSrcTel(),
                order.getSrcProvince(), order.getSrcCity(), order.getSrcDistrict(), order.getSrcAddr())) {
            return "寄件信息不完整";
        }
        if (StringUtils.isAnyBlank(order.getDstName(), order.getDstTel(),
                order.getDstProvince(), order.getDstCity(), order.getDstAddr(), order.getDstAddr())) {
            return "收件信息不完整";
        }
        if (StringUtils.isBlank(order.getCargoName())) {
            return "托寄物品不能为空";
        }
        if (order.getWeight().compareTo(BigDecimal.ZERO) <= 0) {
            return "重量必须大于0";
        }
        if (order.getCargoCnt() <= 0) {
            return "件数必须大于0";
        }
        if (order.getCargoType() <= 0) {
            return "快递类型不正确";
        }
        if (order.getPaySide() <= 0) {
            return "结算方式不正确";
        }
        if (StringUtils.isNotEmpty(order.getOrderNo())) {
            long count = tspOrderMapper.selectCount(new LambdaQueryWrapper<TspOrder>()
                    .eq(TspOrder::getSysAccount, sysAccount)
                    .eq(TspOrder::getOrderNo, order.getOrderNo()));
            if (count > 0) {
                return "运单号[" + order.getOrderNo() + "]已存在";
            }
        }
        return "";
    }
}
